package com.bookstore.servlet;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.bookstore.domain.Account;
import com.bookstore.domain.Book;
import com.bookstore.domain.ShoppingCart;
import com.bookstore.domain.ShoppingCartItem;
import com.bookstore.domain.User;
import com.bookstore.service.AccountService;
import com.bookstore.service.BookService;
import com.bookstore.service.UserService;
import com.bookstore.web.BookStoreWebUtils;
import com.bookstore.web.CriteriaBook;
import com.bookstore.web.Page;
import com.google.gson.Gson;

@WebServlet("/bookServlet")
public class BookServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private BookService bookService = new BookService();
	private UserService userService = new UserService();
	private AccountService accountService = new AccountService();
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String methodName = request.getParameter("method");
		// 反射方式执行方法
		try {
			Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
					HttpServletResponse.class);
			method.setAccessible(true);
			method.invoke(this, request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void getBooks(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String pageNoStr = request.getParameter("pageNo");
		String minPriceStr = request.getParameter("minPrice");
		String maxPriceStr = request.getParameter("maxPrice");

		int pageNo = 1;
		int minPrice = 0;
		int maxPrice = Integer.MAX_VALUE;

		try {
			pageNo = Integer.parseInt(pageNoStr);
		} catch (NumberFormatException e) {
		}

		try {
			minPrice = Integer.parseInt(minPriceStr);
		} catch (NumberFormatException e) {
		}

		try {
			maxPrice = Integer.parseInt(maxPriceStr);
		} catch (NumberFormatException e) {
		}

		CriteriaBook criteriaBook = new CriteriaBook(minPrice, maxPrice, pageNo);
		Page<Book> page = bookService.getPage(criteriaBook);

		request.setAttribute("bookpage", page);

		request.getRequestDispatcher("/WEB-INF/pages/books.jsp").forward(request, response);
		/*response.sendRedirect("/WEB-INF/pages/books.jsp");*/
	}

	protected void getBook(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String idStr = request.getParameter("id");
		Book book = null;
		int id = -1;
		
		try {
			id = Integer.parseInt(idStr);
		} catch (NumberFormatException e) {
		}
		if(id >0)
			book = bookService.getBook(id);
		
		if (book == null) {
			response.sendRedirect(request.getContextPath() + "/error-1.jsp");
			return;
		}
		
		request.setAttribute("book", book);
		
		request.getRequestDispatcher("/WEB-INF/pages/book.jsp").forward(request, response);
	}
	
	protected void addToCart(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//1. 获取商品的id
		String idStr = request.getParameter("id");
		int id = -1;
		boolean flag = false;
		try {
			id = Integer.parseInt(idStr);
		} catch (NumberFormatException e) {
		}
		
		if(id > 0){
			//2. 获取购物车对象
			ShoppingCart sCart = BookStoreWebUtils.getShoppingCart(request);
			
			//3. 调用bookservice的addToCart方法 把商品放到购物车中
			flag = bookService.addToCart(id, sCart);
		}
		
		if (flag) {
			//4. 直接调用getBooks方法转发页面
			getBooks(request, response);
			return;
		}
		response.sendRedirect(request.getContextPath() + "/error-1.jsp");
	}
	
	protected void forwardPage(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String page = request.getParameter("page");
		request.getRequestDispatcher("/WEB-INF/pages/" + page + ".jsp").forward(request, response);
	}
	
	
	protected void remove(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String idStr = request.getParameter("id");
		int id = -1;
		try {
			id = Integer.parseInt(idStr);
		} catch (Exception e) {
		}
		
		ShoppingCart sCart = BookStoreWebUtils.getShoppingCart(request);
		bookService.removeItemFromShoppingCart(sCart, id);
		if (sCart.isEmpty()) {
			request.getRequestDispatcher("/WEB-INF/pages/emptycart.jsp").forward(request, response);
		}else{
			request.getRequestDispatcher("/WEB-INF/pages/cart.jsp").forward(request, response);
		}
	}
	
	protected void clear(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		ShoppingCart sCart = BookStoreWebUtils.getShoppingCart(request);
		bookService.clearShoppingCart(sCart);
		request.getRequestDispatcher("/WEB-INF/pages/emptycart.jsp").forward(request, response);
	}
	
	
	protected void updateItemQuantity(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//4.在updateItemQuantity 方法中，获取 quantity, id, 再获取购物车对象, 调用service 的方法做修改
		String idStr = request.getParameter("id");
		String quantityStr = request.getParameter("quantity");
		int id = -1;
		int quantity = -1;
		try {
			id = Integer.parseInt(idStr);
			quantity = Integer.parseInt(quantityStr);
		} catch (Exception e) {
		}
		ShoppingCart sCart = BookStoreWebUtils.getShoppingCart(request);
		
		if (id > 0 && quantity > 0) {
			bookService.updateItemQuantity(sCart, id, quantity);
		}
		//5.传回json数据: bookNumber totalMoney
		Map<String, Object> result = new HashMap<String, Object>();
		float fItemMoney = sCart.getBooks().get(id).getItemMoney();
		
		result.put("bookNumber", sCart.getBookNumber());
		result.put("totalMoney", sCart.getTotalMoney());
		result.put("itemMoney", fItemMoney);
		Gson gson = new Gson();
		String jsonStr = gson.toJson(result);
		response.setContentType("text/javascript");
		response.getWriter().print(jsonStr);
	}

	/**
	* @Title: checkout
	* @Description: TODO(支付信息校验)
	* @param @param request
	* @param @param response
	* @param @throws ServletException
	* @param @throws IOException    
	* @return void    
	* @throws
	* 2017年6月1日
	*/
	protected void checkout(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		/*1. 简单验证： 验证表单域的值是否符合基本的规范： 是否为空，是否可转为int型，是否是一个email，
		不需要查询数据库或调用任何业务方法就可以完成*/
		String username  = request.getParameter("username");
		String accountId = request.getParameter("accountId");
		StringBuffer errors = validateFormField(username, accountId);
		//表单验证通过
		if (errors.toString().equals("")) {
			errors = validateUser(username, accountId);
			
			//用户名和账户验证通过
			if (errors.toString().equals("")) {
				errors = validateBooksStoreNumber(request);
				
				//库存验证通过
				if (errors.toString().equals("")) {
					// 验证余额
					errors = validateBalance(request, accountId);
				}
			}
		}

		if (!errors.toString().equals("")) {
			request.setAttribute("errors", errors);
			request.getRequestDispatcher("/WEB-INF/pages/checkout.jsp").forward(request, response);
			return;
		}
		
		// 验证通过执行逻辑操作
		bookService.checkout(BookStoreWebUtils.getShoppingCart(request), username, accountId);
		response.sendRedirect(request.getContextPath() + "/success.jsp");
		
	}

	/**
	* @Title: validateBalance
	* @Description: TODO(检验账户余额是否不足)
	* @param @param request
	* @param @param accountId
	* @param @return    
	* @return StringBuffer    
	* @throws
	* 2017年6月2日
	*/
	public StringBuffer validateBalance(HttpServletRequest request, String accountId) {
		ShoppingCart sCart = BookStoreWebUtils.getShoppingCart(request);
		StringBuffer errors = new StringBuffer("");
		Account account = accountService.getAccount(Integer.parseInt(accountId));
		if (sCart.getTotalMoney() > account.getBalance()) {
			errors.append("余额不足");
		}
		return errors;
	}

	/**
	* @Title: validateUser
	* @Description: TODO(检验库存是否充足)
	* @param @param username
	* @param @param accountId
	* @param @return    
	* @return StringBuffer    
	* @throws
	* 2017年6月2日
	*/
	public StringBuffer validateBooksStoreNumber(HttpServletRequest request) {
		ShoppingCart sCart = BookStoreWebUtils.getShoppingCart(request);
		StringBuffer errors = new StringBuffer("");
		for (ShoppingCartItem sCartItem : sCart.getItems()) {
			int quantity = sCartItem.getQuantity();
			
			//由于线程并发问题，操作时的库存可能发生变化，我们不能取内存中的库存，而是需要取数据库中的书籍库存
			int storeNumber = bookService.getBook(sCartItem.getBook().getId()).getStoreNumber();
			
			if (quantity > storeNumber) {
				errors.append(sCartItem.getBook().getTitle() + "库存不足<br>");
			}
		}
		return errors;
	}
	
	/**
	* @Title: validateUser
	* @Description: TODO(检验用户名和账户是否匹配)
	* @param @param username
	* @param @param accountId
	* @param @return    
	* @return StringBuffer    
	* @throws
	* 2017年6月2日
	*/
	public StringBuffer validateUser(String username, String accountId) {
		boolean flag = false;
		User user = userService.getUserByUsername(username);
		if (user != null) {
			int accountId2 = user.getAccountId();
			if (accountId.trim().equals(""+accountId2)) {
				flag = true;
			}
		}
		StringBuffer errors2 = new StringBuffer("");
		if (!flag) {
			errors2.append("用户名和账户不匹配");
		}
		return errors2;
	}
	
	/**
	* @Title: validateFormField
	* @Description: TODO(form表单数据简单验证是否符合规则)
	* @param @return    
	* @return StringBuffer    
	* @throws
	* 2017年6月1日
	*/
	public StringBuffer validateFormField(String username, String accountId) {
		StringBuffer errors = new StringBuffer("");
		if (username == null || username.trim().equals("")) {
			errors.append("用户名不能为空 <br>");
		}
		
		if (accountId == null || accountId.trim().equals("")) {
			errors.append("账户不能为空 <br>");
		}
		return errors;
	}
}



